# write by hasaki
# frist edit on 2019/03/27
# last change on 2019/07/17
# k线一分钟策略,boll策略
# 增加功能：能同时接受多种行情数据，tick/depth/bar，因为gate的K线websocket不稳定，经常断连
# 接口那边没有设计好，断连后的自动重连很难做，所以在策略中实现接收多种行情
# 增加了kdj指标
# 增加KDJ与布林指标的混合判断
from datetime import datetime
import json

from hashakisea.strategy.haStrategyTemplate import HaStrategy
from hashakisea.signal.indicators import indicator

class HaBarTest(HaStrategy):
    def __init__(self):     
        super(HaBarTest,self).__init__()
        self.strategy_name='布林策略'
        self.pos=0         # 持仓
        self.cash=0     # 现金
        self.side=0                 # 判断方向
        self.init_time=0          # 用于
        self.boll_up_line=None    # 布林线的上轨
        self.boll_mid_line=None   # 布林线的中轨
        self.boll_low_line=None   # 布林线的下轨
        self.k=None               # kdj指标结果
        self.d=None
        self.j=None
        self.boll_pos=''          # 判断现在处在布林通道的哪个位置
        self.save_json_path='C:/Users/cchyp/Desktop/hasaki/quote/last_day/data.json'
        self._4hour_history_data_path='C:/Users/cchyp/Desktop/hasaki/quote/last_week/2019-7-3.json'
        self._4hour_history_data_path_new='C:/Users/cchyp/Desktop/hasaki/quote/last_week/2019-7-4.json'
        self.counter_save_time=0
        self.K_of_4_hour=[]       # 从本地加载的4小时历史K线列表
        self.wbhost='https://oapi.dingtalk.com/robot/send?access_token=1723b5ff0e5b5b5c522d520aaf79e747f990b598172e241c6f0ef3c693a6b14f' # 钉钉机器人的APi
        self.pic_url='https://coding.net/u/Kashaki/p/hasaki/git/raw/0.1/quote/last_day/quote.jpg'
    
    def onBar_4h(self,data):
        '''4小时K线'''
        # 更新boll线
        self.update_boll(data)
        # 回调给onBar，因为onBar中有K线操作，不分是什么周期K线
        self.onBar(data)
    
    def next(self,data):
        ''''''
        if self.init_time==0:
            self.get_4_hour_history()
            init_num=len(self.K_of_4_hour)
            self.boll_up_line,self.boll_mid_line,self.boll_low_line= indicator.boll(self.K_of_4_hour,init_num,2)
            self.k,self.d,self.j=indicator.kdj(self.K_of_4_hour,9,3,3)
            self.init_time+=1
            self.save_json(self.pos,self.capital,self.strategy_name,0,'没开仓','没交易',0)
            print('布林线的输出',self.boll_up_line,self.boll_mid_line,self.boll_low_line)
            self.ding(self.wbhost,'布林线的输出:  上轨：{} 中轨：{} 下轨：{}'.format(round(self.boll_up_line*7,4),round(self.boll_mid_line*7,4),round(self.boll_low_line*7,4)))
            self.ding(self.wbhost,'KDJ指标输出: K : {}  D : {}  J : {}'.format(round(self.k,1),round(self.d,1),round(self.j,1)))
            try:
                self.ding(self.wbhost,'EOS 现价 ：{}'.format(round(float(data['close'])*7,4)))
            except KeyError:
                self.ding(self.wbhost,'EOS 现价 ：{}'.format(round(float(data['last'])*7,4)))
            
            #self.pic_ding(self.pic_url,"EOS K线图")
        
        if 'last' not in data:
            # 获取到的行情是K线行情
            self.onBar(data)
        else:
            self.onTick(data)

    def onBar(self,data):
        '''接收K线行情'''
        # 突破上轨的时候
        if data['close']>=self.boll_up_line:
            self.boll_pos='up'
            if self.pos<10:
                print('行情突破boll线上轨，买入')
                self.ding(self.wbhost,'行情突破boll线上轨')
                self.buy('eos_usdt',data['close'],100)
                now=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                self.save_json(self.pos,self.capital,self.strategy_name,self.capital-3000,now,'买进',self.pos)
        
        # 在中线附近时候
        elif data['close']<=self.boll_mid_line+round(self.boll_mid_line*0.01,3) and data['close']>=self.boll_mid_line-round(self.boll_mid_line*0.01,3):
            self.boll_pos='mid'
            if self.pos>10:
                print('boll线在中轨，所有持仓卖出')
                self.ding(self.wbhost,'boll线在中轨')
                self.sell('eos_usdt',data['close'],1000)
                now=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                self.save_json(self.pos,self.capital,self.strategy_name,self.capital-3000,now,'卖出',self.pos)

        # 行情突破了布林线下轨
        elif data['close']<=self.boll_low_line:
            self.boll_pos='low'
            if self.pos>10:
                print('突破布林线的下轨')
        
        # KDJ指标信号做反弹，在上升趋势中，当j小于10就买进
        # 在下跌趋势中，当j大于90就卖出
        if self.boll_pos=='up' and self.j<10:
            print('上行趋势时，j小于10，KDJ进入超卖区，买入信号触发')
            if self.pos<10:
                self.buy('eos_usdt',data['close'],100)
            self.ding(self.wbhost,'上行趋势时，j小于10，KDJ进入超卖区，买入信号触发')
        elif self.j>90 and self.boll_pos=='low':
            print('KDJ进入超买区')
            self.ding(self.wbhost,'下行趋势时，j大于90，KDJ进入超买区，做空信号触发')
            if self.pos>100:
                self.sell('eos_usdt',data['close'],100)
        
        # 更新boll线
        self.transerTime(data)

        if data['name']=='1h':
            self.update_4h_bar(data)

        # 保存成json文件
        if self.counter_save_time==10:
            now=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            self.save_json(self.pos,self.capital,self.strategy_name,self.capital-3000,now,'更新中',self.pos)
        elif self.counter_save_time==20:
            self.counter_save_time=0
        self.counter_save_time+=1
    
    def onTick(self,tick):
        '''接收tick行情'''
        pass
    
    def onDepth(self,tick):
        '''接收到的深度行情'''
        pass
    
    def onOrder(self):
        pass
    
    def onTrade(self):
        pass
    
    def save_json(self,position,capital,strategy_name,startegy_win,orderTime,orderSide,orderVolume):
        '''保存成json'''
        # 读取
        with open(self.save_json_path,'r',encoding='utf-8') as json_file:
            json_data=json.load(json_file)

        # 更新数据
        json_data['position']=position
        json_data['capital']=capital
        json_data['strategyName']=strategy_name
        json_data['strategyWin']=startegy_win
        json_data['orderTime']=orderTime
        json_data['orderSide']=orderSide
        json_data['orderVolume']=orderVolume

        # 写入
        with open(self.save_json_path,'w',encoding='utf-8') as json_file:
            json.dump(json_data,json_file,ensure_ascii=False)
    
    def get_4_hour_history(self):
        '''从本地获取4小时的历史K线
        数据结构:[{'time':'','high':float,'low':float,'open':float,'close':float,'volume':float},{},...]'''
        # 读取
        with open(self._4hour_history_data_path,'r',encoding='utf-8') as json_file:
            json_data=json.load(json_file)
        
        self.K_of_4_hour=json_data

        # 读取
        with open(self._4hour_history_data_path_new,'r',encoding='utf-8') as json_file:
            json_data=json.load(json_file)
        
        for i in json_data:
            self.K_of_4_hour.append(i)
        
        print('读取本地4小时周期历史K线完成')
    
    def update_boll(self,data):
        '''更新boll数据'''
        self.K_of_4_hour.pop(0)
        self.K_of_4_hour.append(data)
        self.boll_up_line,self.boll_mid_line,self.boll_low_line= indicator.boll(self.K_of_4_hour,20,2)
        self.k,self.d,self.j=indicator.kdj(self.K_of_4_hour,9,3,3)